package c18类加载和反射;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;

/**
 * 利用反射给两个不同对象的属性批量赋值。
 *
 * @author ywlPC
 */
public class VOsrc2VOdest {

	/**
	 * 两个不同对象的属性批量赋值。只赋值属性名称对数组指明的属性。
	 *
	 * @param osrc       源对象
	 * @param odest      目标对象
	 * @param fieldsPair 属性名称对数组。第0行储存源对象的，第1行为目标对象，比如{{"i","s"},{"ii","ss"}}。
	 */
	public static void parse(Object osrc, Object odest, String[][] fieldsPair) {
		//对象所属类型
		Class<?> csrc = osrc.getClass();
		Class<?> cdest = odest.getClass();
		//记录赋值过程中出现的错误
		StringBuffer sbsrcm = new StringBuffer();
		StringBuffer sbdestf = new StringBuffer();
		StringBuffer sbdestm = new StringBuffer();

		for (int i = 0; i < fieldsPair[0].length; i++) {
			System.err.println(fieldsPair[0][i] + "--" + fieldsPair[1][i]);
			//属性对应的字符串表示
			String sfsrc = fieldsPair[0][i];
			//拼接属性对应的get方法，比如xxx对应getXxx
			String smsrc = "get" + (sfsrc.charAt(0) + "").toUpperCase() + sfsrc.substring(1, sfsrc.length());
			try {
				//利用反射获取get方法
				Method msrc = csrc.getMethod(smsrc);
				String sfdest = fieldsPair[1][i];
				Field fdest;
				try {
					//获取目标对象的属性
					fdest = cdest.getDeclaredField(sfdest);
					//拼接属性对应的set方法，比如xxx对应setXxx
					String smdest = "set" + (sfdest.charAt(0) + "").toUpperCase() + sfdest.substring(1, sfdest.length());

					Method mdest;
					try {
						//利用反射获取set方法
						mdest = cdest.getMethod(smdest, fdest.getType());
						try {
							System.err.println(msrc.invoke(osrc, null));
							//目标对象调用set方法把从源对象调用get方法获取的值赋给相应的属性
							mdest.invoke(odest, msrc.invoke(osrc, null));
						} catch (IllegalArgumentException e) {
							e.printStackTrace();
						} catch (IllegalAccessException e) {
							e.printStackTrace();
						} catch (InvocationTargetException e) {
							e.printStackTrace();
						}

					} catch (SecurityException e) {
						e.printStackTrace();
					} catch (NoSuchMethodException e) {
						recordErr(sbdestm, cdest, "类的以下属性的set方法不存在：", sfdest);
					}

				} catch (NoSuchFieldException e) {
					recordErr(sbdestf, cdest, "类的以下属性不存在：", sfdest);
				}

			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (NoSuchMethodException e) {
				recordErr(sbsrcm, csrc, "类的以下属性的get方法不存在：", sfsrc);
			}
		}
		printErr(sbsrcm);
		printErr(sbdestf);
		printErr(sbdestm);
	}

	/**
	 * 记录错误信息
	 *
	 * @param sb    总错误信息
	 * @param title 标题
	 * @param err   当前错误信息
	 */
	private static void recordErr(StringBuffer sb, Class c, String title, String err) {
		if ("".equals(sb.toString())) {
			sb.append(c.getSimpleName() + title);
		}
		sb.append(err + ", ");
	}

	/**
	 * 如果错误信息不为空，则打印错误信息。
	 *
	 * @param sb
	 */
	private static void printErr(StringBuffer sb) {
		if (!"".equals(sb.toString())) {
			System.err.println(sb);
		}
	}

	/**
	 * 两个不同对象的属性批量赋值。只赋值属性名称相同的。
	 *
	 * @param osrc  源对象
	 * @param odest 目标对象
	 */
	public static void parseSame(Object osrc, Object odest) {
		//对象所属类型
		Class<?> csrc = osrc.getClass();
		Field[] fields = csrc.getDeclaredFields();
		String[][] fieldsPair = new String[2][fields.length];
		for (int i = 0; i < fields.length; i++) {
			fieldsPair[0][i] = fields[i].getName();
			fieldsPair[1][i] = fields[i].getName();
		}
		parse(osrc, odest, fieldsPair);
	}


	/**
	 * 两个不同对象的属性批量赋值。属性名相同和属性名称对数组指明的属性都赋值。
	 *
	 * @param osrc       源对象
	 * @param odest      目标对象
	 * @param fieldsPair 属性名称对数组。第0行储存源对象的，第1行为目标对象，比如{{"i","s"},{"ii","ss"}}。
	 */
	public static void parseAll(Object osrc, Object odest, String[][] fieldsPair) {
		//先将属性名相同的都赋值
		parseSame(osrc, odest);
		//再把属性字符串对应数组指明的属性赋值
		parse(osrc, odest, fieldsPair);
	}


	public static void main(String[] args) throws SecurityException, NoSuchMethodException {
//		VOsrc osrc=new VOsrc('x',-1, "草泥马");
//		VOdest odest=new VOdest();
//		String[][] fieldsMap={{"i","s"},{"ii","ss"}};
////		parseSame(osrc,odest);
//		parseAll(osrc,odest,fieldsMap);
//		System.err.println(odest);
	}
}
